package com.temp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.temp.dto.RobotCampaignDTO;
import com.temp.dto.SearchCampaignDTO;
import com.temp.dto.SetCampaignDTO;
import com.temp.entity.Campaign;
import com.temp.mapper.CampaignMapper;
import com.temp.service.CampaignService;
import com.temp.vo.CampaignDataVO;
import com.temp.vo.CampaignDetailVO;
import com.temp.vo.CampaignStatusVO;
import com.temp.vo.CustomPageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CampaignServiceImpl extends ServiceImpl<CampaignMapper, Campaign> implements CampaignService {

    @Autowired
    private CampaignMapper campaignMapper;

    @Override
    public Map<String, Object> findCampaignDataByUserId(Long userId) {
        return calculateStats(campaignMapper.findCampaignDataByUserId(userId));
    }

    @Override
    public List<CampaignStatusVO> findCampaignByStatus(SearchCampaignDTO campaignDTO) {
        return campaignMapper.findCampaignByStatus(campaignDTO);
    }

    @Override
    public CustomPageVO<CampaignDetailVO> findAdminCampaignByStatus(SearchCampaignDTO campaignDTO) {
        CustomPageVO<CampaignDetailVO> customPageVO = new CustomPageVO<>();
        Integer count = Optional.ofNullable(campaignMapper.countCampaignDetail(campaignDTO)).orElse(0);
        customPageVO.setTotal(count);
        if(count < 1) {
            customPageVO.setDataList(Collections.emptyList());
            return customPageVO;
        }
        List<CampaignDetailVO> campaignByStatus = campaignMapper.findCampaignDetail(campaignDTO);
        customPageVO.setDataList(campaignByStatus);
        return customPageVO;
    }

    @Override
    public CampaignStatusVO findCampaignById(Long id) {
        return campaignMapper.findCampaignById(id);
    }

    @Override
    public boolean updateCampaignSet(SetCampaignDTO campaignDTO) {
        return campaignMapper.updateCampaignSet(campaignDTO) > 0;
    }

    @Override
    public Campaign getCampaignForUpdate(Long id) {
        return campaignMapper.getCampaignForUpdate(id);
    }

    @Override
    public Integer findAllNotEndedCampaign(Long userId) {
        Integer allNotEndedCampaign = campaignMapper.findAllNotEndedCampaign(userId);
        return Optional.ofNullable(allNotEndedCampaign).orElse(0);
    }

    @Override
    public List<Campaign> findAllCampaignByRobot(RobotCampaignDTO robotCampaignDTO) {
        return campaignMapper.findAllCampaignByRobot(robotCampaignDTO);
    }

    public Map<String, Object> calculateStats(List<CampaignDataVO> data) {
        // 1. 防御性拷贝和空值检查
        List<CampaignDataVO> validData = Optional.ofNullable(data)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 2. 计算总金额（过滤null金额）
        BigDecimal totalAmount = validData.stream()
                .map(CampaignDataVO::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 3. 计算独立支持者数量
        long supporters = validData.stream()
                .map(CampaignDataVO::getDonationUserId)
                .filter(Objects::nonNull)
                .distinct()
                .count();

        // 只计算每个状态下的不重复ID数
        Map<String, Integer> statusCount = validData.stream()
                .collect(Collectors.groupingBy(
                        vo -> Optional.ofNullable(vo.getStatus()).orElse("UNKNOWN"),
                        Collectors.mapping(
                                CampaignDataVO::getId,
                                Collectors.collectingAndThen(
                                        Collectors.toSet(),
                                        Set::size
                                )
                        )
                ));

        // 5. 构建结果Map（使用Collections.unmodifiableMap保证不可变）
        Map<String, Object> result = new HashMap<>();
        result.put("statusCount", Collections.unmodifiableMap(statusCount));
        result.put("totalAmount", totalAmount);
        result.put("supporters", supporters);
        return Collections.unmodifiableMap(result);
    }
}
